from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from kubernetes import config, dynamic, client
from kubernetes.client.rest import ApiException

config.load_kube_config('/usr/serverlessPlatform/kubeclient/config/kube-config.yaml')
core_v1_api = client.CoreV1Api()
apps_v1_api = client.AppsV1Api()
dynamic_client = dynamic.DynamicClient(client.ApiClient())


def list_cluster_nodes():
    node_list = client.CoreV1Api().list_node()
    for node in node_list.items:
        print("%s\t%s" % (node.metadata.name, node.metadata.labels))


def create_deployment(deployment_namespace, container_name, container_image, mount_path, nfs_path, if_exist_rm):
    # create namespace
    resp = None
    try:
        resp = core_v1_api.read_namespace(deployment_namespace)
    except Exception as e:
        if e.status != 404:
            print("create_deployment: Unknown error: %s" % e)
            exit(1)
    if not resp:
        print("create_deployment: namespace %s does not exist. Creating it..." % deployment_namespace)
        namespace_manifest = {
            "apiVersion": "v1",
            "kind": "Namespace",
            "metadata": {
                "name": deployment_namespace
            }
        }
        core_v1_api.create_namespace(namespace_manifest)

    # create deployment
    resp = None
    try:
        resp = apps_v1_api.read_namespaced_deployment("deployment-" + container_name, deployment_namespace)
    except ApiException as e:
        if e.status != 404:
            print("create_deployment: Unknown error: %s" % e)
            exit(1)
    command = "chmod 777 -R %s; /init" % mount_path
    deployment_manifest = {
        "apiVersion": "apps/v1",
        "kind": "Deployment",
        "metadata": {"labels": {"app": container_name}, "name": "deployment-" + container_name},
        "spec": {
            "replicas": 1,
            "selector": {"matchLabels": {"app": container_name}},
            "template": {
                "metadata": {"labels": {"app": container_name}},
                "spec": {
                    "containers": [
                        {
                            "name": container_name,
                            "image": container_image,
                            "imagePullPolicy": "IfNotPresent",
                            "command": ["sh", "-c", command],
                            "volumeMounts": [
                                {
                                    "name": "volume-" + container_name,
                                    "mountPath": mount_path,
                                }
                            ]
                        },
                    ],
                    "volumes": [
                        {
                            "name": "volume-" + container_name,
                            "nfs": {
                                "path": nfs_path,
                                "server": "192.168.205.131",
                            }
                        }
                    ],
                },
            },
        },
    }

    if if_exist_rm:
        if resp:
            print("create_deployment: deployment deployment-%s always exist. deleting it..." % container_name)
            delete_deployment(deployment_namespace, container_name)
        print("create_deployment: deployment deployment-%s does not exist. Creating it..." % container_name)
        apps_v1_api.create_namespaced_deployment(deployment_namespace, deployment_manifest)

    else:
        if resp:
            print("create_deployment: deployment deployment-%s always exist. no change." % container_name)
        else:
            print("create_deployment: deployment deployment-%s does not exist. Creating it..." % container_name)
            apps_v1_api.create_namespaced_deployment(deployment_namespace, deployment_manifest)


def delete_deployment(deployment_namespace, container_name):
    resp = None
    try:
        resp = client.AppsV1Api().read_namespaced_deployment("deployment-" + container_name, deployment_namespace)
    except ApiException as e:
        if e.status != 404:
            print("delete_deployment: Unknown error: %s" % e)
            exit(1)
    if not resp:
        print("delete_deployment: deployment deployment-%s does not exist" % container_name)
    else:
        client.AppsV1Api().delete_namespaced_deployment("deployment-" + container_name, deployment_namespace)
        print("delete_deployment: ok!")


def create_or_update_dynamic_service(service_namespace, service_name,
                                     selector_labels):
    resp = None
    try:
        resp = core_v1_api.read_namespaced_service(service_name, service_namespace)
    except ApiException as e:
        if e.status != 404:
            print("create_deployment: Unknown error: %s" % e)
            exit(1)
    service_manifest = {
        "apiVersion": "v1",
        "kind": "Service",
        "metadata": {"name": service_name},
        "spec": {
            "ports": [
                {"name": "code-server", "port": 8443, "protocol": "TCP", "targetPort": 8443, "nodePort": 30443}
            ],
            "selector": {"app": selector_labels},
            "type": "NodePort",
        },
    }
    if not resp:
        print("create_dynamic_service: service service-%s does not exist. Creating it..." % service_name)
        dynamic_client.resources.get(api_version="v1", kind="Service"). \
            create(body=service_manifest, namespace=service_namespace)
    else:
        print("create_dynamic_service: updating service %s" % service_name)
        service_manifest["spec"]["selector"]["app"] = selector_labels
        dynamic_client.resources.get(api_version="v1", kind="Service"). \
            patch(service_manifest, service_name, service_namespace)


def delete_dynamic_service(service_namespace, service_name):
    resp = None
    try:
        resp = client.CoreV1Api().read_namespaced_service(service_name, service_namespace)
    except ApiException as e:
        if e.status != 404:
            print("delete_dynamic_service: Unknown error: %s" % e)
            exit(1)
    if not resp:
        print("delete_dynamic_service: service %s does not exist" % service_name)
    else:
        dynamic.DynamicClient(client.ApiClient()).resources.get(api_version="v1", kind="Service").delete(
            name=service_name, body={}, namespace=service_namespace)
        print("delete_dynamic_service: ok!")


def code_editor_v2(username, function_name, function_lang, if_exist_rm):
    # select code_editor image by function_lang
    code_editor_dir = {
        'python': "192.168.205.128:30002/code-editor/python27:v1"
    }
    container_image = "192.168.205.128:30002/code-editor/python27:v1"  # default editor
    if function_lang in code_editor_dir.keys():
        container_image = code_editor_dir[function_lang]

    # create deployment
    create_deployment(
        'namespace-' + username,
        function_name,
        container_image,
        "/config/workspace",
        '/data/serverlessPlatform/workspace/' + username + '/' + function_name + '/' + function_name,
        if_exist_rm
    )

    # update dynamic service
    create_or_update_dynamic_service(
        'namespace-' + username,
        'service-' + username,
        function_name
    )


def get_deployment_pod_by_selector(namespace, pod_label):
    try:
        info = core_v1_api.list_namespaced_pod(namespace=namespace, label_selector=pod_label)
        pods_list = [pod.metadata.name for pod in info.items]
        return pods_list
    except Exception as e:
        return None


def get_deployment_pod_log(namespace, pod_label):
    pods_log = []
    pods_list = get_deployment_pod_by_selector(namespace, pod_label)
    try:
        for pod_name in pods_list:
            pod_log_list = core_v1_api.read_namespaced_pod_log(pod_name, namespace).split('\n')
            # print(r[0][:19])
            data = []
            for pod_log in pod_log_list:
                if pod_log:
                    data.append({'time': pod_log[:19], 'context': pod_log[20:]})
            pods_log.append({'pod_name': pod_name, 'pod_log': data})
    except:
        pass
    finally:
        return pods_log


def test(request):
    r = get_deployment_pod_log('openfaas-fn', 'faas_function=lgw-demo')
    print(r)
    return JsonResponse({'r': r})

# namespace = "namespace-code-editor"
# create_deployment(namespace, "code1", "192.168.205.128:30002/code-editor/python27:v1", "/config/workspace", "/data/serverlessPlatform/workspace/")
# create_deployment(namespace, "code2", "192.168.205.128:30002/code-editor/python27:v1", "/config/workspace", "/data/serverlessPlatform/workspace/function2")
#
#
# create_or_update_dynamic_service("namespace-code-editor","sevice-codeone","code1")
#
# delete_dynamic_service(namespace,"sevice-codeone")
# delete_dynamic_service("namespace-code-editor", "codeone")
